home *** CD-ROM | disk | FTP | other *** search
- /* User interface subroutines for AX.25
- * Copyright 1991 Phil Karn, KA9Q
- */
- #include "global.h"
- #ifdef AX25
- #include "mbuf.h"
- #include "timer.h"
- #include "iface.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: ax25user.c,v 1.12 1997/08/19 01:19:22 root Exp root $";
- #endif
-
- void reset_all_ax25 (void);
-
-
- /* Open an AX.25 connection */
- struct ax25_cb *
- open_ax25 (iface, local, theremote, mode, window, r_upcall, t_upcall, s_upcall, user)
- struct iface *iface; /* Interface */
- char *local; /* Local address */
- char *theremote; /* theremote address */
- int mode; /* active/passive/server */
- int16 window; /* Window size in bytes */
- void (*r_upcall) (struct ax25_cb *, int); /* Receiver upcall handler */
- void (*t_upcall) (struct ax25_cb *, int); /* Transmitter upcall handler */
- void (*s_upcall) (struct ax25_cb *, int, int); /* State-change upcall handler */
- int user; /* User linkage area */
- {
- struct ax25_cb *axp;
- char remtmp[AXALEN];
-
- if (theremote == NULLCHAR) {
- theremote = remtmp;
- (void) setcall (theremote, " ");
- }
- if ((axp = find_ax25 (local, theremote, iface)) != NULLAX25 && axp->state != LAPB_DISCONNECTED)
- return NULLAX25;/* Only one to a customer */
- if (axp == NULLAX25 && (axp = cr_ax25 (local, theremote, iface)) == NULLAX25)
- return NULLAX25;
-
- axp->iface = iface;
- axp->window = window;
- axp->r_upcall = r_upcall;
- axp->t_upcall = t_upcall;
- axp->s_upcall = s_upcall;
- axp->user = user;
-
- switch (mode) {
- case AX_SERVER:
- axp->flags.clone = 1;
- /* fall through */
- case AX_PASSIVE:
- axp->state = LAPB_LISTEN;
- return axp;
- case AX_ACTIVE:
- default:
- break;
- }
- switch (axp->state) {
- case LAPB_DISCONNECTED:
- est_link (axp);
- lapbstate (axp, LAPB_SETUP);
- break;
- case LAPB_SETUP:
- free_q (&axp->txq);
- break;
- case LAPB_RECOVERY:
- case LAPB_CONNECTED:
- free_q (&axp->txq);
- est_link (axp);
- lapbstate (axp, LAPB_SETUP);
- break;
- case LAPB_DISCPENDING: /* Ignore */
- default:
- break;
- }
- return axp;
- }
-
-
- /* Send data on an AX.25 connection. Caller provides optional PID. If
- * a PID is provided, then operate in stream mode, i.e., a large packet
- * is automatically packetized into a series of paclen-sized data fields.
- *
- * If pid == -1, it is assumed the packet (which may actually be a queue
- * of distinct packets) already has a PID on the front and it is passed
- * through directly even if it is very large.
- */
- int
- send_ax25 (axp, bp, pid)
- struct ax25_cb *axp;
- struct mbuf *bp;
- int pid;
- {
- struct mbuf *bp1;
- int16 offset, len, size;
-
- if (axp == NULLAX25 || bp == NULLBUF) {
- free_p (bp);
- return -1;
- }
- if (pid != -1) {
- offset = 0;
- len = len_p (bp);
- /* It is important that all the pushdowns be done before
- * any part of the original packet is freed.
- * Otherwise the pushdown might erroneously overwrite
- * a part of the packet that had been duped and freed.
- */
- while (len != 0) {
- size = min (len, axp->paclen);
- (void) dup_p (&bp1, bp, offset, size);
- len -= size;
- offset += size;
- bp1 = pushdown (bp1, 1);
- bp1->data[0] = uchar(pid);
- enqueue (&axp->txq, bp1);
- }
- free_p (bp);
- } else {
- enqueue (&axp->txq, bp);
- }
- return lapb_output (axp);
- }
-
-
- /*lint -esym(18,recv_ax25) */
- /* Receive incoming data on an AX.25 connection */
- struct mbuf *
- recv_ax25 (struct ax25_cb *axp, int16 cnt)
- {
- struct mbuf *bp;
-
- if (axp->rxq == NULLBUF)
- return NULLBUF;
-
- if (cnt == 0) {
- /* This means we want it all */
- bp = axp->rxq;
- axp->rxq = NULLBUF;
- } else {
- bp = ambufw (cnt);
- bp->cnt = pullup (&axp->rxq, bp->data, cnt);
- }
- /* If this has un-busied us, send a RR to reopen the window */
- if (len_p (axp->rxq) < axp->window
- && (len_p (axp->rxq) + bp->cnt) >= axp->window)
- (void) sendctl (axp, LAPB_RESPONSE, RR);
-
- return bp;
- }
-
-
- /* Close an AX.25 connection */
- int
- disc_ax25 (axp)
- struct ax25_cb *axp;
- {
- if (axp == NULLAX25)
- return -1;
- switch (axp->state) {
- case LAPB_LISTEN:
- del_ax25 (axp);
- break;
- case LAPB_DISCPENDING:
- lapbstate (axp, LAPB_DISCONNECTED);
- break;
- case LAPB_CONNECTED:
- case LAPB_RECOVERY:
- free_q (&axp->txq);
- axp->retries = 0;
- (void) sendctl (axp, LAPB_COMMAND, DISC | PF);
- stop_timer (&axp->t3);
- start_timer (&axp->t1);
- lapbstate (axp, LAPB_DISCPENDING);
- break;
- case LAPB_DISCONNECTED:
- default:
- break; /* Ignored */
- }
- return 0;
- }
-
-
- /* Verify that axp points to a valid ax25 control block */
- int
- ax25val (axp)
- struct ax25_cb *axp;
- {
- register struct ax25_cb *axp1;
-
- if (axp == NULLAX25)
- return 0; /* Null pointer can't be valid */
- for (axp1 = Ax25_cb; axp1 != NULLAX25; axp1 = axp1->next)
- if (axp1 == axp)
- return 1;
- return 0;
- }
-
-
- /* Force a retransmission */
- int
- kick_ax25 (axp)
- struct ax25_cb *axp;
- {
- if (!ax25val (axp))
- return -1;
- recover (axp);
- return 0;
- }
-
-
- /* Abruptly terminate an AX.25 connection */
- int
- reset_ax25 (axp)
- struct ax25_cb *axp;
- {
- void (*upcall) (struct ax25_cb *, int);
-
- if (axp == NULLAX25)
- return -1;
- /* Be nice and send a DM - WG7J */
- (void) disc_ax25 (axp);
- upcall = (void (*)(struct ax25_cb *, int)) axp->s_upcall;
- lapbstate (axp, LAPB_DISCONNECTED);
- /* Clean up if the standard upcall isn't in use */
- if (upcall != (void (*)(struct ax25_cb *, int)) s_ascall)
- del_ax25 (axp);
- return 0;
- }
-
-
-
- /* Display AX.25 link level control blocks */
- void
- reset_all_ax25 (void)
- {
- while (Ax25_cb != NULLAX25)
- (void) reset_ax25 (Ax25_cb);
- }
-
- #endif
-